#include "stdafx.h"

DWORD GetRequiredBufferSize (list<wstring>& filesList)
{
	DWORD dwRetVal = 0;

	for (list<wstring>::iterator iter=filesList.begin(); iter!=filesList.end(); iter++)
	{
		dwRetVal += sizeof(wchar_t) * ( iter->length() + 1 );
	}

    return dwRetVal + sizeof(wchar_t);    // add one more for the final null
}

void FillSzzBuffer ( wchar_t* pBuffer, list<wstring>& filesList )
{
	wchar_t* pCurrPos;

    pCurrPos = pBuffer;

	for (list<wstring>::iterator iter=filesList.begin(); iter!=filesList.end(); iter++)
	{
		wcscpy(pCurrPos, iter->c_str());
		pCurrPos = _wcsinc(wcschr(pCurrPos, L'\0'));
	}
                                       // Tack on the final null
    *pCurrPos = L'\0';
}

bool FileOperation::ExecuteOperation(UINT func)
{
	FILEOP_FLAGS flags = FOF_NOCONFIRMMKDIR;

	if(!m_ask)
		flags |= FOF_NOCONFIRMATION;

	if (m_silent)
		flags |= FOF_SILENT | FOF_NOERRORUI;

	if (m_allowundo)
		flags |= FOF_ALLOWUNDO;

	SHFILEOPSTRUCT sf;
	ZeroMemory(&sf, sizeof(sf));

	wchar_t* altFiles;
	if (m_moreFiles.size() > 0)
	{
		if (m_sourceFile != L"")
			m_moreFiles.push_back(wstring(m_sourceFile));
		DWORD dwlength = GetRequiredBufferSize(m_moreFiles);
		
		altFiles = (wchar_t*) new BYTE [dwlength];

		FillSzzBuffer(altFiles, m_moreFiles);
	}

	sf.hwnd = m_parent;
	sf.wFunc = func;
	if (m_moreFiles.size() > 0)
	{
		sf.pFrom = altFiles;
	}
	else
	{
		sf.pFrom = m_sourceFile;
	}
	sf.pTo = m_destFile;
	sf.fFlags = flags;
	 
	int n = SHFileOperation(&sf);
	if (n == 0)
	{
		wcout << m_type << L" Success!\n";
		if (m_moreFiles.size() > 0)
		{
			delete[] altFiles;
		}
		return true;
	}
	else
	{
		wcout << m_type << L" Failed!\n";
		if (m_moreFiles.size() > 0)
		{
			delete[] altFiles;
		}
		return false;
	}
}

FileOperation::FileOperation(HWND parent, LPCWSTR sourceFile, LPCWSTR destFile, DWORD sourceSize, bool ask, bool silent, bool allowundo)
	: FilerFrogElement(parent)
{
	memset(&m_sourceFile, 0, sizeof(m_sourceFile));
	memset(&m_destFile, 0, sizeof(m_sourceFile));

	StrCpyW(m_sourceFile, sourceFile);
	StrCpyW(m_destFile, destFile);

	m_ask = ask;
	m_silent = silent;
	m_allowundo = allowundo;
}

void FileOperation::AddFile(const std::wstring& filePath)
{
	m_moreFiles.push_back(filePath);
}

CopyFileOperation::CopyFileOperation(HWND parent, LPCWSTR sourceFile, LPCWSTR destFile, bool ask, bool silent, DWORD sourceSize)
	: FileOperation(parent, sourceFile, destFile, sourceSize, ask, silent)
{
	m_type = L"CopyFileOrFolder";
}

bool CopyFileOperation::Execute()
{
	return ExecuteOperation(FO_COPY);
}

MoveFileOperation::MoveFileOperation(HWND parent, LPCWSTR sourceFile, LPCWSTR destFile, bool ask, bool silent, DWORD sourceSize)
	: FileOperation(parent, sourceFile, destFile, sourceSize, ask, silent)
{
	m_type = L"MoveFileOrFolder";
}

bool MoveFileOperation::Execute()
{
	return ExecuteOperation(FO_MOVE);
}

DeleteFileOperation::DeleteFileOperation(HWND parent, LPCWSTR file, bool ask, bool silent, bool allowundo, DWORD sourceSize)
	: FileOperation(parent, file, L"", sourceSize, ask, silent, allowundo)
{
	m_type = L"DeleteFileOrFolder";
}

bool DeleteFileOperation::Execute()
{
	return ExecuteOperation(FO_DELETE);
}

RenameFileOperation::RenameFileOperation(HWND parent, LPCWSTR sourceFile, LPCWSTR destFile, bool ask, bool silent, DWORD sourceSize)
: FileOperation(parent, sourceFile, destFile, sourceSize, ask, silent)
{
	m_type = L"RenameFileOrFolder";
}

bool RenameFileOperation::Execute()
{
	return ExecuteOperation(FO_RENAME);
}
